package com.piece.core.framework.util.object;

import com.piece.core.framework.util.collection.ArrayUtil;
import com.piece.core.framework.util.collection.CollectionUtil;
import com.piece.core.framework.util.collection.MapUtil;
import com.piece.core.framework.util.string.StringUtil;
import org.apache.commons.lang3.ArrayUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Object工具
 */
public class ObjectUtil {

    /**
     * 判断对象是否相等（判断引用）
     */
    public static boolean equals(Object source, Object target) {
        if (null == source) {
            return null == target;
        } else if (source instanceof BigDecimal && target instanceof BigDecimal) {
            return equals((BigDecimal) source, (BigDecimal) target);
        } else if (source == target) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean equals(BigDecimal source, BigDecimal target) {
        if (source == target) {
            return true;
        } else if (source != null && target != null) {
            return 0 == source.compareTo(target);
        } else {
            return false;
        }
    }

    public static boolean equalsAny(Object source, Object... array) {
        return CollectionUtil.containsAny(source, array);
    }

    /**
     * 生成hashCode
     */
    public static int hashCode(Object... values) {
        if (null == values) {
            return 0;
        }
        StringBuilder builder = new StringBuilder();
        for (Object object : values) {
            if (null != object) {
                builder.append(object);
            }
        }
        return builder.toString().hashCode();
    }

    /**
     * 生成hashCode
     */
    public static int hashCode(byte[] bytes) {
        if (null == bytes) {
            return 0;
        }
        int hashCode = 0;
        for (byte value : bytes) {
            hashCode += value;
        }
        return hashCode;
    }

    public static boolean isNotNull(Object obj) {
        return !isNull(obj);
    }

    public static boolean isNull(Object obj) {
        return null == obj || obj.equals(null);
    }

    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

    public static boolean isEmpty(Object obj) {
        if (null == obj) {
            return true;
        } else if (obj instanceof CharSequence) {
            return StringUtil.isEmpty((CharSequence)obj);
        } else if (obj instanceof Map) {
            return MapUtil.isEmpty((Map)obj);
        } else if (obj instanceof Iterable) {
            return ArrayUtil.isEmpty((Iterable)obj);
        } else if (obj instanceof Iterator) {
            return ArrayUtil.isEmpty((Iterator)obj);
        } else if (obj instanceof Collection) {
            return CollectionUtil.isEmpty((Collection)obj);
        } else {
            return ArrayUtil.isArray(obj) && ArrayUtil.length(obj) == 0;
        }
    }

    public static <T> T defaultIfNull(T... array) {
        for (T item : array) {
            if (null != item) {
                return item;
            }
        }
        return null;
    }

    /**
     * 生成toString结果
     */
    public static String toString(Object object, Object... values) {
        if (null == object) {
            return null;
        }
        final StringBuilder builder = new StringBuilder();
        builder.append(object.getClass().getSimpleName()).append("[");
        if (ArrayUtils.isEmpty(values)) {
            if (object instanceof List) {
                builder.append(object.toString());
            } else if (object instanceof Map) {
                builder.append(object.toString());
            } else {
                // 属性
                Map<String, Object> fields = BeanUtil.getAllFieldsName(object);
                fields.entrySet().forEach(entry -> {
                    builder.append(entry.getKey())
                            .append("=")
                            .append(entry.getValue())
                            .append(",");
                });
                builder.setLength(builder.length() - 1);
            }
        } else {
            for (Object value : values) {
                builder.append(value).append(",");
            }
            builder.setLength(builder.length() - 1);
        }
        builder.append("]");
        return builder.toString();
    }

    public static Object clone(Object entity) {
        Object clone = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(entity);
            oos.close();

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            clone = ois.readObject();
            ois.close();
        } catch (Exception e) {}

        return clone;
    }
}
